/*
	@file: log/source/detail/LogFormat.cpp
	@author: Wolfhead
 */
#include "detail/LogFormat.h"
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "detail/LogPriorityHelper.h"

namespace logger
{

void LogFormat::format(
	LogDataPtr data_ptr, 
	const std::string& format, 
	std::string& output)
{
	if (format.empty())
	{
		return;
	}

	output.reserve(1024); // magic

	for (size_t i = 0; i != format.size(); ++i)
	{
		if (format[i] == '%')
		{
			++i;
			if (i >= format.size())
			{
				break;
			}
			switch (format[i])
			{
				case 'D':
				{
					append_date_time(data_ptr, output);
					break;
				}
				case 'P':
				{
					append_priority(data_ptr, output);
					break;
				}
				case 'T':
				{
					append_thread_id(data_ptr, output);
					break;
				}
				case 'M':
				{
					append_message(data_ptr, output);
					break;
				}
				case 'F':
				{
					append_filename(data_ptr, output);
					break;
				}
				case 'f':
				{
					append_function(data_ptr, output);
					break;
				}	
				case 'L':
				{
					append_line(data_ptr, output);
					break;
				}				
				default:
					break;
			}
			continue;
		}

		output.append(1, format[i]);
	}
}


void LogFormat::append_priority(LogDataPtr data_ptr, std::string& output)
{
	if (data_ptr->by_name)
	{
		output.append("logger:")
		      .append(data_ptr->name);
	}
	else
	{
		output.append(LogPriorityHelper::priority_to_string(data_ptr->priority));
	}
}

void LogFormat::append_thread_id(LogDataPtr data_ptr, std::string& output)
{
	output.append(boost::lexical_cast<std::string>(data_ptr->context.thread_id));
}

void LogFormat::append_date_time(LogDataPtr data_ptr, std::string& output)
{
	struct tm st_time(boost::posix_time::to_tm(data_ptr->context.time));

	char buffer[128];
	strftime(buffer, sizeof(buffer)-1, "%Y-%m-%d %H:%M:%S", 
		&st_time);

	output.append(buffer);
}

void LogFormat::append_message(LogDataPtr data_ptr, std::string& output)
{
	output.append(data_ptr->message);
}

void LogFormat::append_filename(LogDataPtr data_ptr, std::string& output)
{
	output.append(data_ptr->context.filename);
}

void LogFormat::append_function(LogDataPtr data_ptr, std::string& output)
{
	output.append(data_ptr->context.function);
}

void LogFormat::append_line(LogDataPtr data_ptr, std::string& output)
{
	output.append(boost::lexical_cast<std::string>(data_ptr->context.line));
}

}//namespace logger
